package cron

import (
	"errors"
	"sync"
	"time"
)

//定时任务库
//
//1. 与https://godoc.org/github.com/robfig/cron的区别
//     同一任务执行完成后才会 重新定时， 不按准确时间间隔执行
//2. 所有函数无加锁，非线程安全，不适合高并发场景
//3. AddFunc  Cron Start 之前才能 调用

var (
	ErrTaskAlreadyExist = errors.New("Task Already Exist")
)

type eCronStaus int
const (
	_ eCronStaus = iota
	ECronStatusInit
	ECronStatusWaitStart
	ECronStatusStart
	ECronStatusRunning
	ECronStatusWaitStop
	ECronStatusStop
)


type Cron struct {

	list  map[string] *cronTask //任务列表

	status eCronStaus		 //定时中心的运行状态
	wgTask   *sync.WaitGroup //work group for task
}


func NewCron() *Cron{
	c := &Cron{
		list:   make(map[string]*cronTask),
		status: ECronStatusInit,
		wgTask: new(sync.WaitGroup),
	}

	return c
}

//当前版本，必须在 开始之前执行
func (c* Cron)AddFunc(taskName string, duration time.Duration, f TaskFunc) error{
	var err error
	switch c.status {
	case ECronStatusInit, ECronStatusStop:

		if _, bExist := c.list[taskName]; bExist {
			return ErrTaskAlreadyExist
		}else {
			t := newCronTask(taskName, duration, f)
			c.list[taskName] = t
		}

	default:
		err = errors.New("Unexpected status on AddFunc\n")
	}

	return err
}


func (c* Cron) Start() error{
	var err error
	switch c.status {
	case ECronStatusInit, ECronStatusStop:
		c.status = ECronStatusWaitStart
		for _, t := range c.list {
			t.Start(c.wgTask)
		}

		c.status = ECronStatusRunning
	default:
		err = errors.New("Unexpected status on Start\n")
	}

	return err


}

func (c* Cron) Stop()error {
	var err error
	switch c.status {
	case ECronStatusRunning:
		c.status = ECronStatusWaitStop

		for _, t := range c.list {
			t.Stop()
		}
		c.wgTask.Wait()
		c.status = ECronStatusStop
	default:
		err = errors.New("Unexpected status on Stop\n")
	}

	return err
}

